package util;


import com.xyy.util.Base64;
import com.xyy.util.StringUtil;

import javax.crypto.BadPaddingException;
import javax.crypto.Cipher;
import javax.crypto.IllegalBlockSizeException;
import javax.crypto.NoSuchPaddingException;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.lang.reflect.Field;
import java.lang.reflect.Modifier;
import java.nio.file.Files;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.InvalidKeySpecException;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.Comparator;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeMap;
import java.util.concurrent.ConcurrentHashMap;

/**
 * 签名数据需要传入HashMap,允许value为null，但签名时数据一定要和传输后数据一致
 *
 * @Author: wuqiongda
 * @Date: 2019/10/23 9:38
 */
public class LukeRsaUtil {

    /**
     * 递归深度限制
     */
    public static final int RECURSIVE_DEPTH = 2;
    /**
     * 签名算法
     */
    public static final String SIGN_ALGORITHMS = "SHA256withRSA";

    /**
     * 字节数据转字符串专用集合
     */
    private static final char[] HEX_CHAR = { '0', '1', '2', '3', '4', '5', '6',
            '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
    /**
     *
     */
    private static ConcurrentHashMap<Class, Field[]> concurrentHashMap = new ConcurrentHashMap();
    /**
     * 从文件中输入流中加载公钥
     *
     * @param path
     *            公钥输入流
     * @throws Exception
     *             加载公钥时产生的异常
     */
    public static String loadPublicKeyByFile(String path) throws Exception {
        BufferedReader br = new BufferedReader(new FileReader(path
                + "/publicKey.keystore"));
        try {
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (IOException e) {
            throw new Exception("公钥数据流读取错误");
        } catch (NullPointerException e) {
            throw new Exception("公钥输入流为空");
        }finally {
            br.close();
        }
    }

    /**
     * 从字符串中加载公钥
     *
     * @param publicKeyStr
     *            公钥数据字符串
     * @throws Exception
     *             加载公钥时产生的异常
     */
    public static RSAPublicKey loadPublicKeyByStr(String publicKeyStr)
            throws Exception {
        try {
            byte[] buffer = Base64.decode(publicKeyStr);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            X509EncodedKeySpec keySpec = new X509EncodedKeySpec(buffer);
            return (RSAPublicKey) keyFactory.generatePublic(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("公钥非法");
        } catch (NullPointerException e) {
            throw new Exception("公钥数据为空");
        }
    }

    /**
     * 从文件中加载私钥
     *
     * @param path 私钥文件地址
     * @return 是否成功
     * @throws Exception
     */
    public static String loadPrivateKeyByFile(String path) throws Exception {
        BufferedReader  br = new BufferedReader(new FileReader(path+ "/privateKey.keystore"));
        try {
            String readLine = null;
            StringBuilder sb = new StringBuilder();
            while ((readLine = br.readLine()) != null) {
                sb.append(readLine);
            }
            br.close();
            return sb.toString();
        } catch (IOException e) {
            throw new Exception("私钥数据读取错误");
        } catch (NullPointerException e) {
            throw new Exception("私钥输入流为空");
        }finally {
            br.close();
        }
    }

    public static RSAPrivateKey loadPrivateKeyByStr(String privateKeyStr)
            throws Exception {
        try {
            byte[] buffer = Base64.decode(privateKeyStr);
            PKCS8EncodedKeySpec keySpec = new PKCS8EncodedKeySpec(buffer);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            return (RSAPrivateKey) keyFactory.generatePrivate(keySpec);
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此算法");
        } catch (InvalidKeySpecException e) {
            throw new Exception("私钥非法");
        } catch (NullPointerException e) {
            throw new Exception("私钥数据为空");
        }
    }

    /**
     * 公钥加密过程
     *
     * @param publicKey
     *            公钥
     * @param plainTextData
     *            明文数据
     * @return
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static byte[] encrypt(RSAPublicKey publicKey, byte[] plainTextData)
            throws Exception {
        if (publicKey == null) {
            throw new Exception("加密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.ENCRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此加密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("加密公钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("明文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("明文数据已损坏");
        }
    }

    /**
     * 私钥加密过程
     *
     * @param privateKey
     *            私钥
     * @param plainTextData
     *            明文数据
     * @return
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static byte[] encrypt(RSAPrivateKey privateKey, byte[] plainTextData)
            throws Exception {
        if (privateKey == null) {
            throw new Exception("加密私钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(plainTextData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此加密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("加密私钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("明文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("明文数据已损坏");
        }
    }

    /**
     * 私钥解密过程
     *
     * @param privateKey
     *            私钥
     * @param cipherData
     *            密文数据
     * @return 明文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static byte[] decrypt(RSAPrivateKey privateKey, byte[] cipherData)
            throws Exception {
        if (privateKey == null) {
            throw new Exception("解密私钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.DECRYPT_MODE, privateKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("解密私钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("密文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("密文数据已损坏");
        }
    }

    /**
     * 公钥解密过程
     *
     * @param publicKey
     *            公钥
     * @param cipherData
     *            密文数据
     * @return 明文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static byte[] decrypt(RSAPublicKey publicKey, byte[] cipherData)
            throws Exception {
        if (publicKey == null) {
            throw new Exception("解密公钥为空, 请设置");
        }
        Cipher cipher = null;
        try {
            // 使用默认RSA
            cipher = Cipher.getInstance("RSA");
            // cipher= Cipher.getInstance("RSA", new BouncyCastleProvider());
            cipher.init(Cipher.DECRYPT_MODE, publicKey);
            byte[] output = cipher.doFinal(cipherData);
            return output;
        } catch (NoSuchAlgorithmException e) {
            throw new Exception("无此解密算法");
        } catch (NoSuchPaddingException e) {
            e.printStackTrace();
            return null;
        } catch (InvalidKeyException e) {
            throw new Exception("解密公钥非法,请检查");
        } catch (IllegalBlockSizeException e) {
            throw new Exception("密文长度非法");
        } catch (BadPaddingException e) {
            throw new Exception("密文数据已损坏");
        }
    }

    /**
     * 字节数据转十六进制字符串
     *
     * @param data
     *            输入数据
     * @return 十六进制内容
     */
    public static String byteArrayToString(byte[] data) {
        StringBuilder stringBuilder = new StringBuilder();
        for (int i = 0; i < data.length; i++) {
            // 取出字节的高四位 作为索引得到相应的十六进制标识符 注意无符号右移
            stringBuilder.append(HEX_CHAR[(data[i] & 0xf0) >>> 4]);
            // 取出字节的低四位 作为索引得到相应的十六进制标识符
            stringBuilder.append(HEX_CHAR[(data[i] & 0x0f)]);
            if (i < data.length - 1) {
                stringBuilder.append(' ');
            }
        }
        return stringBuilder.toString();
    }

    /**
     * RSA签名
     * @param content 待签名数据
     * @param privateKey 商户私钥
     * @param encode 字符集编码
     * @return 签名值
     */
    public static String sign(Map<String, Object> content, String privateKey, String encode)
    {
        try
        {
            content = convertTreeMap(content, 0);
            PKCS8EncodedKeySpec priPKCS8    = new PKCS8EncodedKeySpec( Base64.decode(privateKey) );

            KeyFactory keyf                 = KeyFactory.getInstance("RSA");
            PrivateKey priKey               = keyf.generatePrivate(priPKCS8);

            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);

            signature.initSign(priKey);
            signature.update( content.toString().getBytes(encode));

            byte[] signed = signature.sign();

            return Base64.encode(signed);
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return null;
    }

    public static String sign(Map<String, Object> content, String privateKey)
    {
        try
        {
            content = convertTreeMap(content, 0);
            PKCS8EncodedKeySpec priPKCS8    = new PKCS8EncodedKeySpec( Base64.decode(privateKey) );
            KeyFactory keyf = KeyFactory.getInstance("RSA");
            PrivateKey priKey = keyf.generatePrivate(priPKCS8);
            java.security.Signature signature = java.security.Signature.getInstance(SIGN_ALGORITHMS);
            signature.initSign(priKey);
            signature.update( content.toString().getBytes());
            byte[] signed = signature.sign();
            return Base64.encode(signed);
        }
        catch (Exception e)
        {
            System.out.println();
            e.printStackTrace();
        }
        return null;
    }

    /**
     * RSA验签名检查
     * @param content 待签名数据
     * @param sign 签名值
     * @param publicKey 分配给开发商公钥
     * @param encode 字符集编码
     * @return 布尔值
     */
    public static boolean doCheck(Map<String, Object> content, String sign, String publicKey,String encode)
    {
        try
        {
            content = convertTreeMap(content, 0);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));
            java.security.Signature signature = java.security.Signature
                    .getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update( content.toString().getBytes(encode) );

            boolean bverify = signature.verify( Base64.decode(sign) );
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }

    public static boolean doCheck(Map<String, Object> content, String sign, String publicKey)
    {
        try
        {
            content = convertTreeMap(content, 0);
            KeyFactory keyFactory = KeyFactory.getInstance("RSA");
            byte[] encodedKey = Base64.decode(publicKey);
            PublicKey pubKey = keyFactory.generatePublic(new X509EncodedKeySpec(encodedKey));

            java.security.Signature signature = java.security.Signature
                    .getInstance(SIGN_ALGORITHMS);

            signature.initVerify(pubKey);
            signature.update(content.toString().getBytes() );

            boolean bverify = signature.verify( Base64.decode(sign) );
            return bverify;

        }
        catch (Exception e)
        {
            e.printStackTrace();
        }

        return false;
    }

    /**
     * 将map进行字典排序,如果有字段是map类型需要进行排序后再签名或者验签
     * @param map
     * @param i 深度 初始传0
     * @return
     */
    public static Map<String, Object> convertTreeMap(Map<String, Object> map, int i){
        if (i>RECURSIVE_DEPTH){
            return map;
        }
        //字典序排序
        Map<String, Object> packageParams = new TreeMap<>(
                new Comparator<String>() {
                    @Override
                    public int compare(String obj1, String obj2) {
                        // 升序排序
                        return obj1.compareTo(obj2);
                    }
                });
        for (Map.Entry<String, Object> entry: map.entrySet()){
            if (entry.getValue()!=null&&!StringUtil.isEmpty(entry.getValue().toString())&&!"null".equals(entry.getValue().toString())){
                packageParams.put(entry.getKey(), entry.getValue());
            }
        }
        return packageParams;
    }

    public static boolean doCheck(Object o, String sign, String publicKey) throws IllegalAccessException {
        Class c = o.getClass();
        Field[] fields = concurrentHashMap.get(c);
        if (fields==null){
            fields = c.getDeclaredFields();
            concurrentHashMap.put(c, fields);
        }
        Map<String ,Object> map = new HashMap<>(8);
        for(Field field: fields){
            if (!Modifier.isStatic(field.getModifiers())) {
                String name = field.getName();
                field.setAccessible(true);
                Object resultValue = field.get(o);
                map.put(name, resultValue);
            }
        }
        return doCheck(map, sign, publicKey);
    }

    public static String sign(Object o, String privateKey) throws IllegalAccessException {
        Class c = o.getClass();
        Field[] fields = concurrentHashMap.get(c);
        if (fields==null){
            fields = c.getDeclaredFields();
            concurrentHashMap.put(c, fields);
        }
        Map<String ,Object> map = new HashMap<>(8);
        for(Field field: fields){
            if (!Modifier.isStatic(field.getModifiers())) {
                String name = field.getName();
                field.setAccessible(true);
                Object resultValue = field.get(o);
                map.put(name, resultValue);
            }
        }
        return sign(map, privateKey);
    }

    public static void main(String[] args) throws Exception {
//        String pubKey = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsonBrs/nLmZU1paOT8al\n" +
//                "q6oyELZqLXPzMrmh8iCL9ji7CH164CVNQ+WfPJusC8IFlWHauvT0+OuLkVhiMkIW\n" +
//                "8scSCgaw3pjo3Oi15TNgpu/+mzhQcIbfJ8wZOSkGXBT6W0fHlr4GPtGDMi59oA2N\n" +
//                "mpIGqHxI6/iz7RnYAeerr/DrglvRk6Qq0TM/nh3ey4gfRKXHbCJGwc5IiHtzIj8S\n" +
//                "vZGLCNkKIfHW2Eb3L7HbviM7u9enqtTshvVEsZ9vtnjfPevVGvIuQfh+7nysTm77\n" +
//                "jH/hfQPGZb//EjhN3joFlGbv2WSsGLmd3iUjkrSbMXeeVMwfiwDcgLVlPC0QLI3h\n" +
//                "yQIDAQAB\n";
//        String priKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyicGuz+cuZlTW\n" +
//                "lo5PxqWrqjIQtmotc/MyuaHyIIv2OLsIfXrgJU1D5Z88m6wLwgWVYdq69PT464uR\n" +
//                "WGIyQhbyxxIKBrDemOjc6LXlM2Cm7/6bOFBwht8nzBk5KQZcFPpbR8eWvgY+0YMy\n" +
//                "Ln2gDY2akgaofEjr+LPtGdgB56uv8OuCW9GTpCrRMz+eHd7LiB9EpcdsIkbBzkiI\n" +
//                "e3MiPxK9kYsI2Qoh8dbYRvcvsdu+Izu716eq1OyG9USxn2+2eN8969Ua8i5B+H7u\n" +
//                "fKxObvuMf+F9A8Zlv/8SOE3eOgWUZu/ZZKwYuZ3eJSOStJsxd55UzB+LANyAtWU8\n" +
//                "LRAsjeHJAgMBAAECggEATE2VqkmOawUvEvsLXUrvuRsnBH+Bh2V7td0iOmHwj02V\n" +
//                "mb5PCobGq9LyKCv77paAXmSQ38AbBltcrcSRSxt1xVKRAhnz8150fx0xyAAaOZ5u\n" +
//                "ORZrQnxR2SdgTE6dOjN5ABQAWAtkjepq4MJ/zCyerUXldJKRc9A5zYZzC/VgKfPd\n" +
//                "Y3zr3tvvuDngeIkMgZQcuphUjsyPee03xZExX1sg1lBIH7D0Li1srcZ83QrLqlQh\n" +
//                "DTX21uAA157E2DSRzT+mptcY4gRAJgUsGzeFplzl2B8NqhXqXmc2LKI3dGOIv7Pa\n" +
//                "2Y5u6yEaANNxnKKH+ow3G8i9xZxnF1/pnZJfU+4fkQKBgQDX8qDB4WbpwY6nmmM4\n" +
//                "k1k5+7Vtdyc5mecrVmzHfIF5+2mQBO3n1MTABhntIt5Mnqy0HlSQedxZ5ZlOn7yD\n" +
//                "Lld24LlqD20742yNMW2XB+zr3TcJBhXwZq4Kn1hh9hPYxiu8XGJLuwu32ZzlAuHS\n" +
//                "UCn6pcIsBHHAus8XDkj4rRPw3QKBgQDTpuNwLeLILM/myarmnRUN5XDwhIWjMTzJ\n" +
//                "Byn7Kzl8jseT6tHO9mVtzcTbS2kZl296uZJMiIhpB2HvOWwDdymkxkDjoH1Zl9Uu\n" +
//                "ajV9ghO45qe183IthG89oiuSYoq41gysg+9MDUjM90HH3r7KQm5yGYUysDnvsXjM\n" +
//                "06Jnc4IP3QKBgQDQotP6PaHGeoEvIRR31rTANpZk+lflaPJVhpx2Z65YgjTNNlX8\n" +
//                "RC8LL1nhKG0KLcvCAgPFylbAa/mgYugo/Z73dcrt05W/5Mw95eFxp/CZORMxHrYX\n" +
//                "m7zO+oDTtIIcT+p1g/RcIo0Bxbe18wDmxxin13owOOMGR/ZI2j5aNC4t6QKBgBRz\n" +
//                "0xSbCogndGur3zzrvwYZvuEvHS7Y6jPO4mqoEaUMsxKDJYUnYEPNF5HNZrmXXalx\n" +
//                "V0bYBr6HfRo95Ucsc7S9h7W3Y4WN24bhsouPT1KVz20Qul7Vpl5BVo6NwTP9Uzo0\n" +
//                "gaJKwlc0KYIj7zHiW4PhHXL5fo/ACZlZdh8jFVVtAoGAOnX/1Cg0g1/q1GjeYSTM\n" +
//                "tKwoKXz+i7TCkaV1riofhVAWb9YqZhloD3YtzVWu46FtZiRQkZjKt1LBnBuNmpkt\n" +
//                "ZNXFkq1pr5Op8D1GzYt8pzrFogku2pK4Bd/saKnED+TkfYRZU3wRD24j8Gem6+E1\n" +
//                "1TyrIEk1Pb3P6zGx5Zbp1QA=";
        String pubKey ="MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAsonBrs/nLmZU1paOT8al\n" +
                "q6oyELZqLXPzMrmh8iCL9ji7CH164CVNQ+WfPJusC8IFlWHauvT0+OuLkVhiMkIW\n" +
                "8scSCgaw3pjo3Oi15TNgpu/+mzhQcIbfJ8wZOSkGXBT6W0fHlr4GPtGDMi59oA2N\n" +
                "mpIGqHxI6/iz7RnYAeerr/DrglvRk6Qq0TM/nh3ey4gfRKXHbCJGwc5IiHtzIj8S\n" +
                "vZGLCNkKIfHW2Eb3L7HbviM7u9enqtTshvVEsZ9vtnjfPevVGvIuQfh+7nysTm77\n" +
                "jH/hfQPGZb//EjhN3joFlGbv2WSsGLmd3iUjkrSbMXeeVMwfiwDcgLVlPC0QLI3h\n" +
                "yQIDAQAB\n";
        String priKey = "MIIEvQIBADANBgkqhkiG9w0BAQEFAASCBKcwggSjAgEAAoIBAQCyicGuz+cuZlTW\n" +
                "lo5PxqWrqjIQtmotc/MyuaHyIIv2OLsIfXrgJU1D5Z88m6wLwgWVYdq69PT464uR\n" +
                "WGIyQhbyxxIKBrDemOjc6LXlM2Cm7/6bOFBwht8nzBk5KQZcFPpbR8eWvgY+0YMy\n" +
                "Ln2gDY2akgaofEjr+LPtGdgB56uv8OuCW9GTpCrRMz+eHd7LiB9EpcdsIkbBzkiI\n" +
                "e3MiPxK9kYsI2Qoh8dbYRvcvsdu+Izu716eq1OyG9USxn2+2eN8969Ua8i5B+H7u\n" +
                "fKxObvuMf+F9A8Zlv/8SOE3eOgWUZu/ZZKwYuZ3eJSOStJsxd55UzB+LANyAtWU8\n" +
                "LRAsjeHJAgMBAAECggEATE2VqkmOawUvEvsLXUrvuRsnBH+Bh2V7td0iOmHwj02V\n" +
                "mb5PCobGq9LyKCv77paAXmSQ38AbBltcrcSRSxt1xVKRAhnz8150fx0xyAAaOZ5u\n" +
                "ORZrQnxR2SdgTE6dOjN5ABQAWAtkjepq4MJ/zCyerUXldJKRc9A5zYZzC/VgKfPd\n" +
                "Y3zr3tvvuDngeIkMgZQcuphUjsyPee03xZExX1sg1lBIH7D0Li1srcZ83QrLqlQh\n" +
                "DTX21uAA157E2DSRzT+mptcY4gRAJgUsGzeFplzl2B8NqhXqXmc2LKI3dGOIv7Pa\n" +
                "2Y5u6yEaANNxnKKH+ow3G8i9xZxnF1/pnZJfU+4fkQKBgQDX8qDB4WbpwY6nmmM4\n" +
                "k1k5+7Vtdyc5mecrVmzHfIF5+2mQBO3n1MTABhntIt5Mnqy0HlSQedxZ5ZlOn7yD\n" +
                "Lld24LlqD20742yNMW2XB+zr3TcJBhXwZq4Kn1hh9hPYxiu8XGJLuwu32ZzlAuHS\n" +
                "UCn6pcIsBHHAus8XDkj4rRPw3QKBgQDTpuNwLeLILM/myarmnRUN5XDwhIWjMTzJ\n" +
                "Byn7Kzl8jseT6tHO9mVtzcTbS2kZl296uZJMiIhpB2HvOWwDdymkxkDjoH1Zl9Uu\n" +
                "ajV9ghO45qe183IthG89oiuSYoq41gysg+9MDUjM90HH3r7KQm5yGYUysDnvsXjM\n" +
                "06Jnc4IP3QKBgQDQotP6PaHGeoEvIRR31rTANpZk+lflaPJVhpx2Z65YgjTNNlX8\n" +
                "RC8LL1nhKG0KLcvCAgPFylbAa/mgYugo/Z73dcrt05W/5Mw95eFxp/CZORMxHrYX\n" +
                "m7zO+oDTtIIcT+p1g/RcIo0Bxbe18wDmxxin13owOOMGR/ZI2j5aNC4t6QKBgBRz\n" +
                "0xSbCogndGur3zzrvwYZvuEvHS7Y6jPO4mqoEaUMsxKDJYUnYEPNF5HNZrmXXalx\n" +
                "V0bYBr6HfRo95Ucsc7S9h7W3Y4WN24bhsouPT1KVz20Qul7Vpl5BVo6NwTP9Uzo0\n" +
                "gaJKwlc0KYIj7zHiW4PhHXL5fo/ACZlZdh8jFVVtAoGAOnX/1Cg0g1/q1GjeYSTM\n" +
                "tKwoKXz+i7TCkaV1riofhVAWb9YqZhloD3YtzVWu46FtZiRQkZjKt1LBnBuNmpkt\n" +
                "ZNXFkq1pr5Op8D1GzYt8pzrFogku2pK4Bd/saKnED+TkfYRZU3wRD24j8Gem6+E1\n" +
                "1TyrIEk1Pb3P6zGx5Zbp1QA=";

        RSAPublicKey publicKey = LukeRsaUtil.loadPublicKeyByStr(pubKey);
        RSAPrivateKey privateKey = LukeRsaUtil.loadPrivateKeyByStr(priKey);
        String plainText = "公钥加密私钥解密";
        System.out.println("--------------公钥加密私钥解密过程-------------------");
        //公钥加密过程
        byte[] cipherData=LukeRsaUtil.encrypt(publicKey,plainText.getBytes());
        String cipher=Base64.encode(cipherData);
        //私钥解密过程
        byte[] res=LukeRsaUtil.decrypt(privateKey, Base64.decode(cipher));
        String restr=new String(res);
        System.out.println("原文："+plainText);
        System.out.println("加密："+cipher);
        System.out.println("解密："+restr);
        System.out.println();

        System.out.println("--------------私钥加密公钥解密过程-------------------");
        plainText="私钥加密公钥解密";
        //私钥加密过程
        cipherData=LukeRsaUtil.encrypt(privateKey,plainText.getBytes());
        cipher=Base64.encode(cipherData);
        //公钥解密过程
        res=LukeRsaUtil.decrypt(publicKey, Base64.decode(cipher));
        restr=new String(res);
        System.out.println("原文："+plainText);
        System.out.println("加密："+cipher);
        System.out.println("解密："+restr);
        System.out.println();

        System.out.println("---------------私钥签名过程------------------");
        Test test = new Test();
        test.setA("a");
        test.setB("b");
//        Map<String, Object> map = new HashMap<>();
//        map.put("businessId","QA66666");
//        map.put("invoker","YIKUAIQIAN_DOC");
//        map.put("businessIdType", "YIKUAIQIAN_DOC");

        String signstr = LukeRsaUtil.sign(test,priKey);
        System.out.println("签名原串："+test.toString());
        System.out.println("签名串："+signstr);
        System.out.println();

        System.out.println("---------------公钥校验签名------------------");
        System.out.println("签名原串："+test.toString());
        System.out.println("签名串："+signstr);
        Map<String, Object> map1 = new HashMap<>();
        map1.put("businessId", "QA66666");

        System.out.println("验签结果："+LukeRsaUtil.doCheck(test, signstr, pubKey));
        System.out.println();

        StringBuffer stringBuffer = new StringBuffer();
        for (int i=0;i<104857;i++){
            stringBuffer.append("aaaaaaaaaa");
        }
        Map<String, Object> map4 = new HashMap<>(4);
        map4.put("pic", stringBuffer.toString());
        long start = System.currentTimeMillis();
        sign(map4, priKey);
        long end = System.currentTimeMillis();
        System.out.println(end-start+"毫秒");
    }
}
